use std::{rc::Rc, cell::RefCell};

use crate::{native, rtda::{Frame, ExtraType}, instructions::base};

pub fn init() {
    native::register("sun/reflect/Reflection", "getCallerClass", "()Ljava/lang/Class;", get_caller_class);
	native::register("sun/reflect/Reflection", "getClassAccessFlags", "(Ljava/lang/Class;)I", get_class_access_flags);
}

// public static native Class<?> getCallerClass();
// ()Ljava/lang/Class;
fn get_caller_class(frame: Rc<RefCell<Frame>>) {
    // top0 is sun/reflect/Reflection
	// top1 is the caller of getCallerClass()
	// top2 is the caller of method
    let caller_frame = frame.borrow().get_thread().lock().unwrap().get_frames()[2].clone(); // TODO
    let caler_class = caller_frame.borrow().get_method().get_class().get_j_class();
    frame.borrow().get_operand_stack().borrow_mut().push_ref(caler_class);
}

// public static native int getClassAccessFlags(Class<?> type);
// (Ljava/lang/Class;)I
fn get_class_access_flags(frame: Rc<RefCell<Frame>>) {
    let vars = frame.borrow().get_local_vars();
    let _type = vars.borrow().get_ref(0);

    if let Some(ExtraType::Class(rs_class)) = unsafe { &*_type.unwrap() }.get_extra() {
        let flags = unsafe { &*rs_class }.get_access_flags();

        let stack = frame.borrow().get_operand_stack();
        stack.borrow_mut().push_int(flags as i32);
    }
}